package com.hp.bon.sgw.service;

import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.sql.DataSource;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.DatabaseConfiguration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.hibernate.SessionFactory;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.hp.bon.sgw.Constants.ConfigPrefix;
import com.hp.bon.sgw.bean.BlacklistRuleView;
import com.hp.bon.sgw.bean.BlockRequestBean;
import com.hp.bon.sgw.bean.CapabilityCtrlBean;
import com.hp.bon.sgw.bean.CapabilityLifeBean;
import com.hp.bon.sgw.bean.CapabilityLimitCfgBean;
import com.hp.bon.sgw.bean.SensitivtyCfg;
import com.hp.bon.sgw.bean.SysParamBean;
import com.hp.bon.sgw.core.ChannelServer;
import com.hp.bon.sgw.domain.BlackListResult;
import com.hp.bon.sgw.domain.BlacklistRule;
import com.hp.bon.sgw.domain.CapabilityAbnLmtCfg;
import com.hp.bon.sgw.domain.FluxCtrlByKeyRule;
import com.hp.bon.sgw.domain.HomeQueryTagConfig;
import com.hp.bon.sgw.domain.Node;
import com.hp.bon.sgw.domain.ProvTrafficLmtCfg;
import com.hp.bon.sgw.domain.SGWCapabilityProvided;
import com.hp.bon.sgw.domain.SGWChannel;
import com.hp.bon.sgw.domain.TPHcode;
import com.hp.bon.sgw.util.Comutils;
import com.hp.bon.sgw.util.LogBackConfigTool;
import com.hp.bon.sgw.util.XmlValidatorDef;
import com.hp.bon.sgw.util.dcc.DccAvpHelper;

/**
 * 负责读取系统配置参数，系统配置参数存在于两处，程序本地文件方式存储以及远程JDBC存储， 当数据库无法访问时，加载本地参数
 * hsqldb配置信息包括(需要checkpoint
 * )：channel,node,capability,capabilityOpen,capabilityProvide
 * ,sysparam(configration)
 * 文件配置：dictionary.xml,delayCallConfig.json,sysparams.conf
 * 
 * @author wuzhih
 * 
 */
@Component
public class ConfigService
{
  private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ConfigService.class);
  private DataSource dataSource;
  private TableBaseConfLoader tableBasedConfLoader;
  private volatile Configuration curConfig;
  private String localConfigFile = "./data/checkpoint.properties";
  private String sysParamFile = "./etc/sysparams.conf";
  private String delayCallFile = "./etc/delayCallConfig.json";
  private String requestValidatorXMlpath = "./etc/bonrequestvalidator.xml";
  private String answerValidatorPatternPath = "./etc/xmlpatterns";
  private final List<ConfigListener> configListeners = new CopyOnWriteArrayList<ConfigListener>();
  private SessionFactory sessionFact;
  private volatile Map<String, CapabilityCtrlBean> capabilityCtrlMap = Collections.emptyMap();
  private volatile Map<String, SysParamBean> curSysParams;
  private volatile Map<String, HomeQueryTagConfig> homeQueryTagConfigMap = Collections.emptyMap();
  private volatile Map<String, BlockRequestBean> requestBlockMap = Collections.emptyMap();

  private volatile Map<String, XmlValidatorDef> requestValiatorDefMap = Collections.emptyMap();

  public static volatile Map<String, StreamSource> answerValidatorMap = new HashMap<String, StreamSource>();

  public static volatile Map<Integer, SGWChannel> sgwChannelMap = new HashMap<Integer, SGWChannel>();
  public static volatile Collection<SGWCapabilityProvided> capabilityProvidedList = new ArrayList<SGWCapabilityProvided>();

  public static ConcurrentHashMap<String, Node> name2NodeMap = new ConcurrentHashMap<String, Node>();
  public static ConcurrentHashMap<Integer, Node> id2NodeMap = new ConcurrentHashMap<Integer, Node>();

  public static ConcurrentHashMap<String, SGWCapabilityProvided> capabiltyProvidedMap = new ConcurrentHashMap<String, SGWCapabilityProvided>();

  public static ConcurrentHashMap<String, TPHcode> tpHcodes99Map = new ConcurrentHashMap<String, TPHcode>();
  private ConcurrentHashMap<String, CapabilityLimitCfgBean> capabilityLimitCfgMap = new ConcurrentHashMap<String, CapabilityLimitCfgBean>();
  public static String sgwHostId;
  public static String sgwHostIP;
  public static String areaCode;
  public static String realm;
  public static String realmWithoutAreaCode;
  
  private ConcurrentHashMap<String, BlackListResult> blackListResultMap = new ConcurrentHashMap<String, BlackListResult>();
  private ConcurrentHashMap<String, BlacklistRuleView> blackRuleCfgMap = new ConcurrentHashMap<String, BlacklistRuleView>();
  
  public static ConcurrentHashMap<String, Node> srMap = new ConcurrentHashMap<String, Node>();
  
  //SGW_PROV_TRAFFIC_LMT_CFG,按省进行总量限流,key=prov
//	public static ConcurrentHashMap<String, Map<String, ProvTrafficLmtCfg>> provTrafficLmtCfgMap = new ConcurrentHashMap<String, Map<String, ProvTrafficLmtCfg>>();

//  // SGW_CAPABILITY_ABN_LMT_CFG,SGW_CAPABILITY_ABN_RC_CFG 特定错码限流配置表,key=prov
//	public static ConcurrentHashMap<String, CapabilityAbnLmtCfg> capabilityAbnLmtCfgMap = new ConcurrentHashMap<String, CapabilityAbnLmtCfg>();
//	
//	public void setCapabilityAbnLmtCfgMap(ConcurrentHashMap<String, CapabilityAbnLmtCfg> capabilityAbnLmtCfgMap) {
//		ConfigService.capabilityAbnLmtCfgMap = capabilityAbnLmtCfgMap;
//	}
	
  public void init()
    throws Exception
  {
    Configuration config = loadConfFromDB();
    if (config == null) {
      config = loadConfNatively();
    }
    else {
      saveConfigToLocal();
    }
    if (config == null) {
      throw new RuntimeException("no configration found");
    }

    loadSysParams(true);

    sgwHostId = this.curConfig.getString("SGW_HOST_ID");
    if ((sgwHostId == null) || ("".equals(sgwHostId.trim()))) {
      sgwHostId = "SGW@001.ctnbc-bon.net";
      logger.error("Cannot find 'SGW_HOST_ID' config, use default " + sgwHostId);
    }
    sgwHostIP = this.curConfig.getString("SGW_HOST_IP");
    if ((sgwHostIP == null) || ("".equals(sgwHostIP.trim()))) {
      sgwHostIP = "0.0.0.0";
      logger.warn("Cannot find 'SGW_HOST_IP' config, use default " + sgwHostIP);
    }

    areaCode = DccAvpHelper.getArea(sgwHostId);
    realm = DccAvpHelper.getRealmPart(sgwHostId);
    realmWithoutAreaCode = DccAvpHelper.getRealmWithoutAreaCode(sgwHostId);

    reloadDelayCallFile();
    loadValidatorXmls();
    loadAnswerXmlPatterns();
  }

  public void checkLazyEffectedSysParams()
  {
  }

  public String reloadAllConfig()
  {
    Configuration curUsing = this.curConfig;
    Configuration config = loadConfFromDB();
    ChannelServer.updateRouteConfig(this);
    long curTime = System.currentTimeMillis();
    if (config == null) {
      return "FAIL: Read DB ERR";
    }

    Map<String,SysParamBean> sysParams = this.curSysParams;
    if ((sysParams != null) && (!sysParams.isEmpty())) {
      for (Entry<String,SysParamBean> entry : sysParams.entrySet()) {
        this.curConfig.addProperty((String)entry.getKey(), ((SysParamBean)entry.getValue()).getValue());
      }
    }
    boolean changed = false;
    
    for (ConfigListener lisnter : configListeners) {
		for (String monitorKey : lisnter.monitorConfKeys()) {
			String newVal = config.getString(monitorKey);
			String oldVal = curUsing.getString(monitorKey);
			changed = (newVal != null) && !newVal.equals(oldVal);
			if (changed) {
				logger.info("update changed config ,key is:" + monitorKey);
				lisnter.onConfigUpdated(monitorKey);
			}
		}
	}

    saveConfigToLocal();

    return "SUCCESS: Used time:" + (System.currentTimeMillis() - curTime) + "ms";
  }

  public String saveConfigToLocal()
  {
    logger.info("checkpoint : save config to local " + this.localConfigFile);
    try {
      ((PropertiesConfiguration)this.curConfig).save(this.localConfigFile);
    } catch (ConfigurationException e) {
      logger.warn("checkpoint save file err,errocode 102 ," + e);
      return "Failed:,errcode 102 " + e.toString();
    }
    return "SUCCESS: saved to file:" + this.localConfigFile;
  }

  public String reloadSysParamFile()
  {
    String result = "SUCCESS";
    try {
      loadSysParams(false);
    } catch (Exception e) {
      result = "ERROR :" + e.getLocalizedMessage();
    }
    return result;
  }

  public String listSysParams(String param) {
    Collection<SysParamBean> allParams = this.curSysParams.values();
    Collection<SysParamBean> resutsParams = null;
    if ((param == null) || (param.length() == 0)) {
      resutsParams = allParams;
    } else if (param.endsWith(".*")) {
      param = param.substring(0, param.length() - 2);
      resutsParams = new LinkedList<SysParamBean>();
      for (SysParamBean theBean : allParams) {
        if (theBean.getName().startsWith(param))
          resutsParams.add(theBean);
      }
    }
    else if ((param.contains("*")) || (param.contains("?")))
    {
      String pat_str = param.replaceAll("\\*", ".*");
      if (pat_str.endsWith("?")) {
        pat_str = pat_str.substring(0, pat_str.length() - 1);
        pat_str = pat_str + ".$";
      }
      while (pat_str.contains("?")) {
        pat_str = pat_str.replace('?', '.');
      }
      if ((!pat_str.startsWith("*")) && (!pat_str.startsWith("."))) {
        pat_str = "^" + pat_str;
      }
      char c = pat_str.charAt(pat_str.length() - 1);
      if ((Character.isDigit(c)) || (Character.isLetter(c))) {
        pat_str = pat_str + "$";
      }
      logger.info("param [" + param + "] convert to regex [" + pat_str + "]");
      resutsParams = new LinkedList<SysParamBean>();
      Pattern pattern = null;
      try {
        pattern = Pattern.compile(pat_str);
      } catch (Exception e) {
        pattern = null;
      }
      if (pattern != null) {
        Matcher m = null;
        for (SysParamBean theBean : allParams) {
          m = pattern.matcher(theBean.getName());
          if ((m != null) && (m.find())) {
            resutsParams.add(theBean);
          }
          m = null;
        }
      }
    } else {
      resutsParams = new LinkedList<SysParamBean>();
      SysParamBean bean = (SysParamBean)this.curSysParams.get(param);
      if (bean != null) {
        resutsParams.add(bean);
      }
    }
    return new Gson().toJson(resutsParams);
  }

  public String setSysParam(String paramValue) {
    if ((paramValue == null) || (paramValue.isEmpty())) {
      return "No param ";
    }
    Map<String, String> params = null;
    try {
      params = Comutils.parseSysParamStr(paramValue);
    } catch (Exception e) {
      return "bad format:" + e.getLocalizedMessage();
    }
    if (params.isEmpty())
    {
      return "no any param";
    }

    String param1 = "agreement.all.outcount_errorlogin";
    String param2 = "agreement.all.time_enablelogin";
    boolean relatedParamsNotSeen = ((params.containsKey(param1)) && (!params.containsKey(param2))) || ((params.containsKey(param2)) && (!params.containsKey(param1)));
    if (relatedParamsNotSeen) {
      return "must provide both of param " + param1 + " and " + param2;
    }
    String effecTime = (String)params.get("effdate");
    StringBuilder result = new StringBuilder();
    for (Entry<String, String> entry : params.entrySet()) {
      String paramKey = (String)entry.getKey();
      String paramVal = (String)entry.getValue();
      if (!paramKey.equals("effdate"))
      {
        try
        {
          result.append(doSetSysParam(paramKey, paramVal, effecTime)).append("\r\n");
        } catch (Exception e) {
          return "SET PARAM ERROR:" + e.toString();
        }
      }
    }
    return result.toString();
  }

  private void loadSysParams(boolean isStartup)
    throws Exception
  {
    File sysParamFile = new File(this.sysParamFile);

    logger.info("load system params from " + sysParamFile.getAbsolutePath());
    Map<String, SysParamBean> newSysparamsMap = Comutils.loadSysParams(sysParamFile);
    boolean updated = false;
    for (SysParamBean newParamBean : newSysparamsMap.values())
    {
      if (isStartup)
      {
        if (("reboot".equals(newParamBean.getEffectiveType())) && (newParamBean.getNewValue() != null)) {
          newParamBean.setValue(newParamBean.getNewValue());
          newParamBean.setNewValue(null);
          updated = true;
        }
        this.curConfig.addProperty(newParamBean.getName(), newParamBean.getValue());
      }
      if (tryUpdatesysParam(newParamBean, isStartup, new StringBuilder())) {
        updated = true;
      }
    }
    if (updated)
    {
      Comutils.saveSysParams(newSysparamsMap, sysParamFile);
    }
    this.curSysParams = newSysparamsMap;
  }

  private boolean tryUpdatesysParam(SysParamBean newParamBean, boolean isStartup, StringBuilder updateInfo) throws ParseException
  {
    String existValue = this.curConfig.getString(newParamBean.getName());
    String newValue = null;
    boolean updated = false;
    String updatedDesc = null;
    if (existValue == null) {
      newValue = newParamBean.getValue();
      updateInfo.append("no memory param found :");
    }
    else if ("realtime".equals(newParamBean.getEffectiveType())) {
      if (newParamBean.getEffectiveTime() != null) {
        long effecTime = Comutils.parseStringTime(newParamBean.getEffectiveTime(), "yyyyMMddHHmm");

        if (effecTime < System.currentTimeMillis()) {
          updated = true;
          updatedDesc = "it's time to load delayed effective param,effectTime is" + newParamBean.getEffectiveTime();
          newValue = newParamBean.getNewValue();
          newParamBean.setValue(newValue);
          newParamBean.setNewValue(null);
          newParamBean.setEffectiveTime(null);
        }
      }
      else if (!existValue.equals(newParamBean.getValue())) {
        newValue = newParamBean.getValue();
        updated = true;
        updatedDesc = " load realtime effective param";
      }
    }

    if (updated) {
      String updateTime = Comutils.formatTime(System.currentTimeMillis(), "yyyyMMddHHmm");
      newParamBean.setLastModifiedTime(updateTime);
      String upInfo = "param:" + newParamBean.getName() + "  oldValue:" + existValue + " newValue:" + newValue + " updateTime:" + updateTime + " note:" + updatedDesc;
      updateInfo.append(upInfo).append("\r\n");
      logger.info(upInfo);

      if (newParamBean.getName().equals("log.level")) {
        String logXmlFile = System.getProperty("SGW_HOME") + File.separator + "etc";
        try {
          LogBackConfigTool.updateAllLogBackProperty(logXmlFile, "Logger.Level", newParamBean.getValue());

          if ("DEBUG".equalsIgnoreCase(newParamBean.getValue()))
            java.util.logging.Logger.getLogger("com.hp.ocs").setLevel(Level.ALL);
          else
            java.util.logging.Logger.getLogger("com.hp.ocs").setLevel(Level.INFO);
        }
        catch (Exception e) {
          updateInfo.append("error:" + e);
          logger.warn("upate  sgw node log properties file err:" + e);
        }
      }
      else if (newParamBean.getName().equals("log.path")) {
        String logXmlFile = System.getProperty("SGW_HOME") + File.separator + "etc";
        try {
          LogBackConfigTool.updateAllLogBackProperty(logXmlFile, "Logger.Dir", newParamBean.getValue());
          updateAgentPropies("SGW_logPath", newParamBean.getValue(), updateInfo);
        } catch (Exception e) {
          updateInfo.append("error:" + e);
          logger.warn("upate  sgw node log properties  err:" + e);
        }
      }
      else if (newParamBean.getName().equals("log.size")) {
        String logXmlFile = System.getProperty("SGW_HOME") + File.separator + "etc";
        try {
          LogBackConfigTool.updateAllLogBackProperty(logXmlFile, "Logger.Size", newParamBean.getValue());
        } catch (Exception e) {
          updateInfo.append("error:" + e);
          logger.warn("upate  sgw node log properties file err:" + e);
        }
      }
      else if (newParamBean.getName().equals("log.log_archive_path")) {
        String logXmlFile = System.getProperty("SGW_HOME") + File.separator + "etc";
        try {
          LogBackConfigTool.updateAllLogBackProperty(logXmlFile, "Archive.Logger.Dir", newParamBean.getValue());
          updateAgentPropies("SGW_logArchivePath", newParamBean.getValue(), updateInfo);
        } catch (Exception e) {
          updateInfo.append("error occured:" + e);
          logger.warn("upate  log properties file err:" + e);
        }

      }

      this.curConfig.setProperty(newParamBean.getName(), newValue);
      if (!isStartup) {
        for (ConfigListener lisnter : this.configListeners) {
          String propKey = newParamBean.getName();
          if (lisnter.monitorConfKeys().contains(propKey)) {
            lisnter.onConfigUpdated(newParamBean.getName());
          }
        }
      }

    }

    return updated;
  }

  private String doSetSysParam(String paramKey, String paramVal, String effectime) throws Exception {
    String result = "";
    boolean saveFile = false;

    SysParamBean paramBean = (SysParamBean)this.curSysParams.get(paramKey);

    if (paramBean == null) {
      return "Not supported param:" + paramKey;
    }

    if (!paramBean.valiate(paramVal)) {
      return "invalid param value:" + paramKey + "=" + paramVal + ",validate failed[" + paramBean.getValueRegex() + "]";
    }

    if (paramKey.equals("business.reconnection")) {
      paramBean.setValue(paramVal);
      paramBean.setEffectiveTime(effectime);
      saveFile = true;
      paramBean = (SysParamBean)this.curSysParams.get("agreement.dcc.timeout_linkwait");
    }

    if ("reboot".equals(paramBean.getEffectiveType()))
    {
      paramBean.setNewValue(paramVal);
      paramBean.setEffectiveTime(null);
      saveFile = true;
      result = "param will updated after reboot " + paramKey;
    }
    else if (effectime != null)
    {
      if (effectime.length() != "yyyyMMddHHmm".length()) {
        throw new Exception("input value:" + effectime + " validate failed[" + "yyyyMMddHHmm" + "]");
      }
      Comutils.parseStringTime(effectime, "yyyyMMddHHmm");
      paramBean.setNewValue(paramVal);
      paramBean.setEffectiveTime(effectime);
      saveFile = true;
      result = "param will updated at effect time:" + effectime + " " + paramKey;
    }
    else {
      paramBean.setValue(paramVal);
      paramBean.setEffectiveTime(null);
      StringBuilder info = new StringBuilder();
      saveFile = tryUpdatesysParam(paramBean, false, info);
      result = info.toString();
    }

    if (saveFile) {
      Map<String, SysParamBean> newParams = new LinkedHashMap<String, SysParamBean>(this.curSysParams);
      newParams.put(paramKey, paramBean);
      this.curSysParams = newParams;

      Comutils.saveSysParams(newParams, new File(this.sysParamFile));
      result = result + " save confige file success";
    }
    return result;
  }

  private void updateAgentPropies(String key, String value, StringBuilder updateInfo) {
    if ((value != null) && (!value.isEmpty()) && (new File(value).isDirectory())) {
      String agentProp = System.getProperty("SGW_HOME") + File.separator + "etc" + File.separator + "RmiAgent.properties";
      try {
        LogBackConfigTool.save2PropertiesFile(key, value, this.curConfig.getString("sgwagent_properties_file", agentProp));
      } catch (Exception e) {
        logger.warn("save agent properties file err:" + e);
      }
    }
  }

  private Configuration loadConfFromDB()
  {
    logger.info(" try load config from database ");
    PropertiesConfiguration propConfig = new PropertiesConfiguration();
    propConfig.setDelimiterParsingDisabled(true);
    try {
      DatabaseConfiguration dbConfig = new DatabaseConfiguration(this.dataSource, "configuration", "key", "newvalue");
      dbConfig.setDelimiterParsingDisabled(true);

      propConfig.copy(dbConfig);
      dbConfig = null;
      this.curConfig = propConfig;

      this.tableBasedConfLoader.loadtoConfig(this);
      if (propConfig.isEmpty()) {
        logger.warn(" config in database is empty ");
        return null;
      }
      logger.info("success load config from database ");
      return propConfig;
    } catch (Exception e) {
      logger.warn(" can't load config from database ", e);
    }

    return null;
  }

  private Configuration loadConfNatively() {
    logger.info("load local config from " + new File(this.localConfigFile).toURI());
    PropertiesConfiguration propConfig = null;
    try {
      propConfig = new PropertiesConfiguration();
      propConfig.setDelimiterParsingDisabled(true);
      propConfig.load(this.localConfigFile);
      if (propConfig.isEmpty()) {
        logger.warn(" config in local is empty ");
        return null;
      }

			// ��һЩMap���ת��Ϊ���󣬹��������ֱ�ӷ���
			convertMapDatasFromJson(propConfig);
		} catch (Exception e) {
			logger.error("load local config err " + e.toString());
		}
		this.curConfig = propConfig;
		return propConfig;
	}

	private void convertMapDatasFromJson(PropertiesConfiguration propConfig) {

		String key = ConfigPrefix.Common_Nodes;
		String conf = propConfig.getString(key, null);
		ConcurrentHashMap<Integer, Node> allNodes = null;
		if (conf != null) {
			allNodes = new Gson().fromJson(conf, new TypeToken<ConcurrentHashMap<String, Node>>() {
			}.getType());
			this.setId2NodeMap(allNodes, false);
		}

		key = ConfigPrefix.Common_Channels;

		conf = propConfig.getString(key, null);
		Map<Integer, SGWChannel> channelMap = null;
		if (conf != null) {
			channelMap = new Gson().fromJson(conf, new TypeToken<Map<Integer, SGWChannel>>() {
			}.getType());
			this.setSgwChannelMap(channelMap, false);
		}

		key = ConfigPrefix.Common_CapabilityCtrlMap;
		conf = propConfig.getString(key, null);
		Map<String, CapabilityCtrlBean> capabilityCtrlMap = null;
		if (conf != null) {
			capabilityCtrlMap = new Gson().fromJson(conf, new TypeToken<Map<String, CapabilityCtrlBean>>() {
			}.getType());
			this.setCapabilityCtrlMap(capabilityCtrlMap, false);
		}

		key = "Common.HomeQueryTagConfigMap";
		conf = propConfig.getString(key, null);
		Map<String, HomeQueryTagConfig> homeQueryTagConfigMap = null;
		if (conf != null) {
			homeQueryTagConfigMap = new Gson().fromJson(conf, new TypeToken<Map<String, HomeQueryTagConfig>>() {
			}.getType());
			this.setHomeQueryTagConfigMap(homeQueryTagConfigMap, false);
    }
  }

  public void setLocalConfigFile(String localConfigFile)
  {
    this.localConfigFile = localConfigFile;
  }

	public Configuration getCurConfig() {
		return curConfig;
	}

	public Map<String, CapabilityCtrlBean> getCapabilityCtrlMap() {
		return capabilityCtrlMap;
	}

	public void setCapabilityCtrlMap(Map<String, CapabilityCtrlBean> capabilityCtrlMap, boolean addJson) {
		this.capabilityCtrlMap = capabilityCtrlMap;
		if (addJson) {
			Gson gson = new Gson();
			this.curConfig.addProperty(ConfigPrefix.Common_CapabilityCtrlMap, gson.toJson(capabilityCtrlMap));
		}
	}

	public Map<String, HomeQueryTagConfig> getHomeQueryTagConfigMap() {
		return homeQueryTagConfigMap;
	}

	public void setHomeQueryTagConfigMap(Map<String, HomeQueryTagConfig> homeQueryTagConfigMap, boolean addJson) {
		this.homeQueryTagConfigMap = homeQueryTagConfigMap;
		if (addJson) {
			Gson gson = new Gson();
			this.curConfig.addProperty("Common.HomeQueryTagConfigMap", gson.toJson(homeQueryTagConfigMap));
		}
	}

	public Node getNodeByName(String hostId) {
		return name2NodeMap.get(hostId);
	}

	public void addConfigListener(ConfigListener listener) {
		configListeners.add(listener);
	}

	public void addConfigListener(int index, ConfigListener listener) {
		configListeners.add(index, listener);
	}

	public String getValue(String name, String defaultValue) {
		return curConfig.getString(name, defaultValue);
	}

	public int getIntValue(String name, int defaultValue) {
		return curConfig.getInt(name, defaultValue);
	}

	public double getDoubleValue(String name, double defaultValue) {
		return curConfig.getDouble(name, defaultValue);
	}

	public long getLongValue(String name, long defaultValue) {
		return curConfig.getLong(name, defaultValue);
	}

	public boolean getBooleanValue(String name, boolean defaultValue) {
		return curConfig.getBoolean(name, defaultValue);
	}

  @Transactional("transactionManager")
  public void updateChannelStatus2DB(int channelId, int status) {
    try {
      StringBuilder sb = new StringBuilder();
      sb.append("update SGWChannel set status =").append(status);
      sb.append(",statusTime = sysDate");
      sb.append(" where id= ").append(channelId);
      this.sessionFact.getCurrentSession().createQuery(sb.toString()).executeUpdate();
      logger.debug(sb.toString());
    } catch (Exception e) {
      logger.warn("update channel status to DB failed :channelId=" + channelId + "," + "status=" + status + "," + e.toString());
    }
  }

  @Transactional("transactionManager")
  public void updateNodeStatus2DB(int nodeId, int status) {
    try {
      StringBuilder sb = new StringBuilder();
      sb.append("update Node set status =").append(status);
      sb.append(",statusTime = sysDate");
      sb.append(" where id= ").append(nodeId);
      this.sessionFact.getCurrentSession().createQuery(sb.toString()).executeUpdate();
      logger.debug(sb.toString());
    } catch (Exception e) {
      logger.warn("update node status to DB failed :nodeId=" + nodeId + "," + "status=" + status + "," + e.toString());
    }
  }

	/**
	 * serviceFlowId���� SGW �汾
	 * 
	 * @return
	 */
	public String getSGWVersion() {
		return this.curConfig.getString(SysParamBean.KEY_SYSTEM_Version, "2.0");
	}

	/**
	 * serviceFlowId���� SGW ��Ԫ���
	 * 
	 * @return
	 */
	public String getSGWNeCode() {
		return this.curConfig.getString(SysParamBean.KEY_SYSTEM_NECODE, "001000000");
	}

	public String getAreaCode() {
		return areaCode;
	}

	public String getRealm() {
		return realm;
	}

	public String getRealmWithoutAreaCode() {
		return realmWithoutAreaCode;
	}

  public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  public void setSysParamFile(String sysParamFile) {
    this.sysParamFile = sysParamFile;
  }

  public Map<Integer, SGWChannel> getSgwChannelMap() {
    return sgwChannelMap;
  }

	public void setName2NodeMap(ConcurrentHashMap<String, Node> name2NodeMap) {
		ConfigService.name2NodeMap = name2NodeMap;
	}

	public void setCapabilityProvidedList(Collection<SGWCapabilityProvided> capabilityProvidedList, boolean addJson) {
		ConfigService.capabilityProvidedList = capabilityProvidedList;

		if (addJson) {
			curConfig.addProperty(ConfigPrefix.Common_CapaProvideds, new Gson().toJson(ConfigService.capabilityProvidedList));
		}
	}

	public void setCapabiltyProvidedMap(ConcurrentHashMap<String, SGWCapabilityProvided> capabiltyProvidedMap) {
		ConfigService.capabiltyProvidedMap = capabiltyProvidedMap;
	}

	public void setTPHcodes99(ConcurrentHashMap<String, TPHcode> tpHcodes99Map) {
		ConfigService.tpHcodes99Map = tpHcodes99Map;
  }

	public void setId2NodeMap(ConcurrentHashMap<Integer, Node> id2NodeMap, boolean addJson) {
		ConfigService.id2NodeMap = id2NodeMap;
		if (addJson) {
			GsonBuilder builder = new GsonBuilder();
			builder.excludeFieldsWithoutExposeAnnotation();
			Gson gson = builder.create();
			curConfig.addProperty(ConfigPrefix.Common_Nodes, gson.toJson(ConfigService.id2NodeMap));
		}
	}

	public void setSgwChannelMap(Map<Integer, SGWChannel> sgwChannelMap, boolean addJson) {
		ConfigService.sgwChannelMap = sgwChannelMap;

		if (addJson) {
			Gson gson = new Gson();
			this.curConfig.addProperty(ConfigPrefix.Common_Channels, gson.toJson(ConfigService.sgwChannelMap));
		}
	}

  public String reloadDelayCallFile()
  {
    logger.info("load delay call file from " + this.delayCallFile);
    try {
      this.requestBlockMap = Comutils.loadDelayCapParams(new File(this.delayCallFile));
      return "SUCCESS";
    } catch (Exception e) {
      logger.warn("load file err:" + e);
      return "FAILED:" + e.toString();
    }
  }

	/**
	 * ������ϢУ�������ļ�
	 * 
	 * @return
	 */
	public String loadValidatorXmls() {
		logger.info("load capability request validator xml file " + requestValidatorXMlpath);
		SAXReader reader = new SAXReader();
		Document document = null;
		try {
			document = reader.read(requestValidatorXMlpath);
			requestValiatorDefMap = SGWCapabilityReqXMLValidator.parseDefXml(document);
		} catch (DocumentException e) {
			logger.error("load err:" + e);
			return "ERR:" + e;
		}
		logger.info("load capability validators ,total " + this.requestValiatorDefMap.size());
		return "SUCESS";
	}

	/**
	 * ����Ӧ����ϢУ������ from file
	 * 
	 * @return
	 */
	public String loadAnswerXmlPatterns() {
		logger.info("load answer validator pattern path defines from dir:" + answerValidatorPatternPath);
		File fileDir = new File(this.answerValidatorPatternPath);

		// System.out.println("test:" + fileDir.getAbsolutePath());
		Map<String, StreamSource> map = new HashMap<String, StreamSource>();
		String capability = "";
		String fileName = "";

		for (File file : fileDir.listFiles()) {
			fileName = file.getName();
			if (file.isFile() && fileName.endsWith(".xsd")) {
				try {
					capability = fileName.substring(0, fileName.lastIndexOf("."));
					StreamSource ss = new StreamSource(file);
					map.put(capability, ss);
				} catch (Exception e) {
					logger.error("load err: " + file + " " + e);
				}
			}
		}
		answerValidatorMap = map;
		logger.info("load answer validator pattern def " + map.size());
		return "SUCESS";
	}
	
  public Map<String, BlockRequestBean> getRequestBlockMap() {
    return this.requestBlockMap;
  }

	public Map<String, XmlValidatorDef> getValiatorDefMap() {
		return requestValiatorDefMap;
	}

  @Autowired
  public void setTableBasedConfLoader(TableBaseConfLoader tableBasedConfLoader) {
    this.tableBasedConfLoader = tableBasedConfLoader;
  }
  @Autowired
  @Qualifier("sessionFactory")
  public void setSessionFact(SessionFactory sessionFact) {
    this.sessionFact = sessionFact;
  }

  public static HashMap<String, BlacklistRule> blacklistRuleMap = new HashMap<String, BlacklistRule>();
  public void setBlacklistRuleMap(HashMap<String, BlacklistRule> pblacklistRuleMap) {
	  blacklistRuleMap = pblacklistRuleMap;
  }
  
  public ConcurrentHashMap<String, CapabilityLimitCfgBean> getCapabilityLimitCfgMap() {
		return capabilityLimitCfgMap;
	}
	
  public void setCapabilityLimitCfgMap(ConcurrentHashMap<String, CapabilityLimitCfgBean> capabilityLimitCfgMap) {
	this.capabilityLimitCfgMap = capabilityLimitCfgMap;
  }
  
  public ConcurrentHashMap<String, BlackListResult> getBlackListResultMap() {
		return blackListResultMap;
	}
	
	public void setBlackListResultMap(ConcurrentHashMap<String, BlackListResult> blackListResultMap) {
		this.blackListResultMap = blackListResultMap;
	}
	
	public ConcurrentHashMap<String, BlacklistRuleView> getBlackRuleCfgMap() {
		return blackRuleCfgMap;
	}
	
	public void setBlackRuleCfgMap(ConcurrentHashMap<String, BlacklistRuleView> blackRuleCfgMap) {
		this.blackRuleCfgMap = blackRuleCfgMap;
	}
	private ConcurrentHashMap<String, CapabilityLifeBean> capabilityLifeCfgMap = new ConcurrentHashMap<String, CapabilityLifeBean>();
	public ConcurrentHashMap<String, CapabilityLifeBean> getCapabilityLifeCfgMap() {
		return capabilityLifeCfgMap;
	}
	
	public void setCapabilityLifeCfgMap(ConcurrentHashMap<String, CapabilityLifeBean> capabilityLifeCfgMap) {
		this.capabilityLifeCfgMap = capabilityLifeCfgMap;
	}
	private ConcurrentHashMap<String, SensitivtyCfg> sensitivtyCfgMap = new ConcurrentHashMap<String, SensitivtyCfg>();
	public ConcurrentHashMap<String, SensitivtyCfg> getSensitivtyCfgMap() {
		return sensitivtyCfgMap;
	}
	
	public void setSensitivtyCfgMap(ConcurrentHashMap<String, SensitivtyCfg> sensitivtyCfgMap) {
		this.sensitivtyCfgMap = sensitivtyCfgMap;
	}
	
//	// SGW_PROV_TRAFFIC_LMT_CFG,按省进行总量限流,key=prov
//	public static ConcurrentHashMap<String, Map<String, ProvTrafficLmtCfg>> provTrafficLmtCfgMap = new ConcurrentHashMap<String, Map<String, ProvTrafficLmtCfg>>();
//
//	public void setProvTrafficLmtCfgMap(ConcurrentHashMap<String, Map<String, ProvTrafficLmtCfg>> provTrafficLmtCfgMap) {
//		ConfigService.provTrafficLmtCfgMap = provTrafficLmtCfgMap;
//	}
//	
//	public static Map<String, Map<String,FluxCtrlByKeyRule>>  fluxCtrlByKeyRuleMap = new HashMap<String, Map<String,FluxCtrlByKeyRule>> ();
//	public void setFluxCtrlByKeyRuleMap(Map<String, Map<String,FluxCtrlByKeyRule>> fluxCtrlByKeyRuleMap){
//		this.fluxCtrlByKeyRuleMap = fluxCtrlByKeyRuleMap;
//	}
	
	//Map<capability,Map<key,FluxCtrlByKeyRule>>
	public static Map<String, Map<String, FluxCtrlByKeyRule>> list2FluxCtrlByKeyRuleMap(List<FluxCtrlByKeyRule> fluxCtrlByKeyRuleList) {

		Map<String, Map<String,FluxCtrlByKeyRule>>  fluxCtrlByKeyRuleMap = new HashMap<String, Map<String,FluxCtrlByKeyRule>> ();
		for (FluxCtrlByKeyRule rule : fluxCtrlByKeyRuleList) {
			rule.setKeyAvpPath(DccAvpHelper.convertXPath2AvpPath(rule.getXmlTag()));
			Map<String,FluxCtrlByKeyRule> fluxCtrlByKeyRuleMapSub = fluxCtrlByKeyRuleMap.get(rule.getCapability());
			if(fluxCtrlByKeyRuleMapSub == null)
			{
				fluxCtrlByKeyRuleMapSub =  new HashMap<String,FluxCtrlByKeyRule>();
				fluxCtrlByKeyRuleMap.put(rule.getCapability(), fluxCtrlByKeyRuleMapSub);
			}
			fluxCtrlByKeyRuleMapSub.put(rule.getKey(), rule);
		}
		return fluxCtrlByKeyRuleMap;
	}
	
	//Map<node,Map<provid,ProvTrafficLmtCfg>>
	public static ConcurrentHashMap<String, Map<String, ProvTrafficLmtCfg>> list2FluxCtrlByNodeRuleMap(List<ProvTrafficLmtCfg> provTrafficLmtCfgList) {

		ConcurrentHashMap<String, Map<String,ProvTrafficLmtCfg>>  fluxCtrlByNodeRuleMap = new ConcurrentHashMap<String, Map<String,ProvTrafficLmtCfg>>();
		for (ProvTrafficLmtCfg rule : provTrafficLmtCfgList) {
			Map<String,ProvTrafficLmtCfg> fluxCtrlByNodeRuleMapSub = fluxCtrlByNodeRuleMap.get(rule.getNode());
			if(fluxCtrlByNodeRuleMapSub == null)
			{
				fluxCtrlByNodeRuleMapSub =  new HashMap<String,ProvTrafficLmtCfg>();
				fluxCtrlByNodeRuleMap.put(rule.getNode(), fluxCtrlByNodeRuleMapSub);
			}
			fluxCtrlByNodeRuleMapSub.put(rule.getProvId(), rule);
		}
		return fluxCtrlByNodeRuleMap;
	}
}